﻿using System;
using System.Text;

namespace BiliBiliLiveDanMuTool.Utils
{
    /// <summary>
    /// 动态缓冲区管理器
    /// </summary>
    public class DynamicBufferManager
    {
        /// <summary>
        /// 缓冲区
        /// </summary>
        public byte[] Buffer { get; set; }
        /// <summary>
        /// 已写入数据大小
        /// </summary>
        public int DataCount { get; set; }
        /// <summary>
        /// 当前数据指针
        /// </summary>
        public int DataPoint { get; set; }

        /// <summary>
        /// 动态缓冲管理器
        /// </summary>
        /// <param name="bufferSize">缓冲区大小</param>
        public DynamicBufferManager(int bufferSize)
        {
            DataPoint = 0;
            DataCount = 0;
            Buffer = new byte[bufferSize];
        }

        /// <summary>
        /// 获得当前写入字节数
        /// </summary>
        /// <returns></returns>
        public int GetDataCount()
        {
            return DataCount;
        }

        /// <summary>
        /// 获得缓冲区可用字节数
        /// </summary>
        /// <returns></returns>
        public int GetReserveCount()
        {
            return Buffer.Length - DataCount;
        }

        /// <summary>
        /// 清空缓冲区字节计数器
        /// </summary>
        public void Clear()
        {
            DataCount = 0;
            DataPoint = 0;
        }

        /// <summary>
        /// 清除指定大小的数据
        /// </summary>
        /// <param name="count">清除数据大小</param>
        public void Clear(int count)
        {
            if (count >= DataCount)
            {
                DataCount = 0;
            }
            else
            {
                for (int i = 0; i < DataCount - count; i++) // 数据前移
                {
                    Buffer[i] = Buffer[count + i];
                }
                DataCount = DataCount - count;
            }
        }

        /// <summary>
        /// 设置缓存大小
        /// </summary>
        /// <param name="size">新缓存大小</param>
        public void SetBufferSize(int size)
        {
            if (Buffer.Length < size)
            {
                byte[] _tmpBuffer = new byte[size];
                Array.Copy(Buffer, 0, _tmpBuffer, 0, DataCount);
                Buffer = _tmpBuffer;
            }
        }

        /// <summary>
        /// 写入缓冲区
        /// </summary>
        /// <param name="buffer">需要写入的数据</param>
        /// <param name="offset">偏移量</param>
        /// <param name="count">数据大小</param>
        public void WriteBuffer(byte[] buffer, int offset, int count)
        {
            if (GetReserveCount() >= count)
            {
                Array.Copy(buffer, offset, Buffer, DataCount, count);
                DataCount += count;
            }
            else // 扩展缓冲区
            {
                int _totalSize = Buffer.Length + count - GetReserveCount();
                byte[] _tmpBuffer = new byte[_totalSize];
                Array.Copy(Buffer, 0, _tmpBuffer, 0, DataCount);
                Array.Copy(buffer, offset, _tmpBuffer, DataCount, count);
                DataCount += count;
                Buffer = _tmpBuffer;
            }
        }

        /// <summary>
        /// 写入缓冲区
        /// </summary>
        /// <param name="buffer">需要写入的数据</param>
        public void WriteBuffer(byte[] buffer)
        {
            WriteBuffer(buffer, 0, buffer.Length);
        }

        /// <summary>
        /// 写入短整形
        /// </summary>
        /// <param name="value">值</param>
        /// <param name="convert">是否转换为网络字节序</param>
        public void WriteShort(short value, bool convert)
        {
            if (convert)
            {
                value = System.Net.IPAddress.HostToNetworkOrder(value);
            }
            byte[] _tmpBuffer = BitConverter.GetBytes(value);
            WriteBuffer(_tmpBuffer);
        }

        /// <summary>
        /// 写入整形
        /// </summary>
        /// <param name="value">值</param>
        /// <param name="convert">是否转换为网络字节序</param>
        public void WriteInt(int value, bool convert)
        {
            if (convert)
            {
                value = System.Net.IPAddress.HostToNetworkOrder(value);
            }
            byte[] _tmpBuffer = BitConverter.GetBytes(value);
            WriteBuffer(_tmpBuffer);
        }

        /// <summary>
        /// 写入长整型
        /// </summary>
        /// <param name="value">值</param>
        /// <param name="convert">是否转换为网络字节序</param>
        public void WriteLong(long value, bool convert)
        {
            if (convert)
            {
                value = System.Net.IPAddress.HostToNetworkOrder(value);
            }
            byte[] _tmpBuffer = BitConverter.GetBytes(value);
            WriteBuffer(_tmpBuffer);
        }

        /// <summary>
        /// 写入字符串
        /// </summary>
        /// <param name="value">值</param>
        /// <param name="convert">是否转换为网络字节序</param>
        public void WriteString(string value, bool convert)
        {
            byte[] _tmpBuffer = Encoding.UTF8.GetBytes(value);
            WriteBuffer(_tmpBuffer);
        }

        /// <summary>
        /// 从缓冲区当中读取整形
        /// </summary>
        /// <returns></returns>
        public int ReadToInt(bool convert)
        {
            int _value = BitConverter.ToInt32(Buffer, DataPoint);
            DataPoint += 4;
            if (convert) return System.Net.IPAddress.NetworkToHostOrder(_value);
            else return _value;
        }
    }
}
